/*
LCDMenu.h - Library for showing Menu on LCDs
Original Author: CWAL
License: Just leave this header, do anything else with it you want

*/

#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "global.h"
#include "LCDMenu.h"


int LCDMenu::gx(int which){
	return (which%prow)*(charx/prow);
}

int LCDMenu::gy(int which){
	return (which/prow);
}


LCDMenu::LCDMenu(Menu &r,ShaggyLCD &d){
	rootMenu=&r;
	curMenu=rootMenu;
	lcd=&d;
	prow=1;
	charx=16;
	chary=2;
	options(prow,1,0,1);
	scroll = 0;
}

LCDMenu::LCDMenu(Menu &r,ShaggyLCD &d,int pr){
	rootMenu=&r;
	curMenu=rootMenu;
	lcd=&d;
	prow=pr;
	charx=20;
	chary=4;
	options(prow,1,1,1);
}

LCDMenu::LCDMenu(Menu &r,ShaggyLCD &d,int pr,int cx,int cy){
	rootMenu=&r;
	curMenu=rootMenu;
	lcd=&d;
	prow=pr;
	charx=cx;
	chary=cy;
	options(prow,1,1,1);
}

void LCDMenu::options(int pr,char o,char b,char c){
	prow=pr;
	offset=o;
	showBack=b  ;
	cursor=c;
}

void LCDMenu::setCursor(){
	if (cursor){
		lcd->command(0x0F);
	}
	else{
		lcd->command(0x0E);
	}
	lcd->setCursor(gx(curloc),gy(curloc)-scroll);
}

void LCDMenu::doScroll(){
	if (curloc<0){
		curloc=0;
	}
	else{
		while (curloc>0&&!curMenu->getChild(curloc-showBack)){//Only allow it to go up to Menu item (one more if back button enabled)
			curloc--;
		}
	}
	int wherey=gy(curloc);
	if (wherey>=(chary+scroll)){
		scroll++;
		display();
	}
	else if (wherey<(scroll)){
		scroll--;
		display();
	}
	else{
		setCursor();
	}
}

void LCDMenu::goUp(){
	curloc-=prow;
	doScroll();
}

void LCDMenu::goDown(){
	curloc+=prow;
	doScroll();
}

void LCDMenu::goLeft(){
	curloc--;
	doScroll();
}

void LCDMenu::goRight(){
	curloc++;
	doScroll();
}

void LCDMenu::goBack() {
	goMenu(*curMenu->getParent());
}

void LCDMenu::goEnter(){
	Menu *tmp;
	tmp=curMenu;
	if ((tmp=tmp->getChild(curloc))){//The child exists	 
		if (tmp->canEnter){//canEnter function is set
			if (tmp->canEnter(*tmp)){//It wants us to enter
				//goMenu(*tmp); by def comment
				curMenu = tmp;
				curloc = 0;
				scroll = 0;
				if(curMenu->display){
					curMenu->display();
				}
			}
		}
		else{//canEnter function not set, assume entry allowed
			goMenu(*tmp);
		}
	}
	else{//Child did not exist  The only time this should happen is one the back Menu item, so go bac
		goBack();
	}
}

void LCDMenu::goMenu(Menu &m){
	curMenu=&m;
	curloc=0;
	scroll= 0;
	//printf("goEnter: %s\r\n",curMenu->name);
	display();
}

void LCDMenu::goMenu_noDisplay(Menu &m){
	curMenu=&m;
	curloc=0;
	scroll= 0;
}

void LCDMenu::display(){
	Menu * tmp;
	int i=scroll*prow;
	int maxi=((chary+scroll)*prow);
	lcd->clear();
	if ((tmp=curMenu->getChild(i))){
		do{
			lcd->setCursor(gx(i)+offset,gy(i)-scroll);	
			lcd->LCD_string(tmp->name);
			i++;
		}
		while ((tmp=tmp->getSibling(1))&&i<maxi);
		if ((i<=maxi)&&showBack){ //We stopped before the end of the lcd, so draw the back button if needed
			lcd->setCursor(gx(i)+offset,gy(i)-scroll);
			lcd->LCD_string("Back");  
		}
	}
	else{ //Menu has no children
		lcd->setCursor(0,0);
		lcd->LCD_string("No Children");
	}
	setCursor();
}

void LCDMenu::refreshNow(){
	if (curMenu->refreshNow() == REFRESH_NOW){
		curMenu->display();
	}
}

void LCDMenu::keyPress(char key){
	char c;
	int i;
	//0 -no key pressed
	//1 - enter
	//2 - back
	//3 - up
	//4 - down
	//5 - start
	//6 - pause.
	Menu *tmp;
	i=0;
	//	printf("Menu: %s\r\n",curMenu->name);
	if (curMenu->keyPress){
		i = 1;
		c = curMenu->keyPress(key);
		if (c == 0){
			//	printf("c = 0\r\n");
			goBack();
		}
	}
	
	if (i==0){
		switch (key){
			case ENTER_KEY:
				goEnter();
				break;
			case BACK_KEY:
				goBack();
				break;
			case UP_KEY:
				goUp();
				break;
			case DOWN_KEY:
				goDown();
				break;
			default:
				break;
		}
	}
	
}
